
* Replication
*
* Talk or Type? The Effect of Digital Interfaces on Citizens’ Satisfaction with Standardized Public Services
* by Christine Prokop and Markus Tepe
* Public Administration 2021


version 15
set more off
cd "~\Replication"
clear
import excel using "data.xlsx" , first
save "data.dta", replace

***************
*** Coding ****
***************

* Create long dataset (reshape from wide to long)
gen id = _n

* Drop quota fails
drop if Progress!=100

* Clean dataset
drop vign1_timer* vign2_timer* vign3_timer*
gen vpr1 = vign1_1
gen vpr2 = vign2_1
gen vpr3 = vign3_1
gen vre1 = vign1_2
gen vre2 = vign2_2
gen vre3 = vign3_2
encode wasesist1     , gen(act1)
encode wasesist2     , gen(act2)
encode wasesist3     , gen(act3)
encode komebene1     , gen(com1)
encode komebene2     , gen(com2)
encode komebene3     , gen(com3)
encode serviceebene1 , gen(qual1)
encode serviceebene2 , gen(qual2)
encode serviceebene3 , gen(qual3)
drop if vpr1==.
drop if vpr2==.
drop if vpr3==.
drop if technik1_1 ==.
drop if technik1_2 ==.
drop if technik1_3 ==.
drop if technik1_4 ==.
drop if technik1_5 ==.
drop if technik1_6 ==.
drop if technik2_1 ==.
drop if technik2_2 ==.
drop if technik2_3 ==.
drop if technik2_4 ==.
drop if technik2_5 ==.
drop if technik2_6 ==.

* Create long dataset (reshape from wide to long)
reshape long vpr vre act com qual, i(id) j(period) 

* Dependent variables
lab var vpr "Satisfaction with procedure"
lab var vre "Satisfaction with result"

* General satisfaction
gen sat = (vpr+vre)/2
lab var sat "Satisfaction"

* Type of service
recode act 1=2 2=1 3=3
lab def actlbl ///
	1 "Passport" ///
	2 "Clearance certificate" ///
	3 "Social housing"
lab val act actlbl

* Communication channel
recode com 1=2 2=3 3=1
lab def comlbl ///
	1 "Face-to-face" ///
	2 "SST" ///
	3 "App"
lab val com comlbl

* Service quality
recode qual 1=1 2=1 3=1 4=2 5=3 6=2 7=3 8=2 9=3
lab def quallbl ///
	1 "No Failure" ///
	2 "Failure with expl." ///
	3 "Failure without expl." 
lab val qual quallbl

* Expectation satisfaction with public service
gen expr = exp_1
label var expr "Expectation Procedure"
gen exre = exp_2
label var exre "Expectation Result"
gen exp = (expr+exre)/2
lab var exp "Expectation"
xtile exp_nq3 = exp, nq(3)
lab var exp_nq3 "EXP Quartile"

* Gender 
gen fem =0
replace fem =1 if geschlecht==1
lab def femlbl ///
	1 "Female" ///
	0 "Male"
lab val fem femlbl
label var fem "Female"

* Age
gen age = alter
label var age "Age"
recode age 18/35=1 36/55=2 56/max=3 , gen(age3)

* Save coded dataset
save data_coded.dta, replace
use data_coded.dta, clear


****************
*** Analysis ***
****************

* Descriptive statistics
tabstat sat vre vpr exp exre expr age fem, s(n mean sd min max) c(s)

* Vignette response grouped by Quality (Figure 1)
use data_coded.dta, clear
collapse (mean) meansat=sat (sd) sdsat=sat (count) n=sat ,by(act qual com)
generate hisat = meansat + invttail(n-1,0.025)*(sdsat / sqrt(n))
generate losat = meansat - invttail(n-1,0.025)*(sdsat / sqrt(n))
generate actqual = qual    if act == 1
replace  actqual = qual+5  if act == 2
replace  actqual = qual+10 if act == 3 
sort actqual
list actqual act qual com, sepby(act)
save data_collapsed.dta, replace
* -> use R script

	
* tsset data
use data_coded.dta, clear
tsset id period

* set base
fvset base 1 com
fvset base 3 qual 
fvset base 1 act 

* Figure 2. Baseline Treatment Effects
xtreg sat i.act i.qual i.com                    i.period   , re rob 
margins act qual com , post mcompare(sidak)
coefplot, xtitle(Predicted value,size(medium))     ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
			graph save fig2a.gph, replace		
xtreg sat i.act i.qual i.com                    i.period   , re rob 
margins, dydx(act qual com) post mcompare(sidak)
coefplot, xline(0) xtitle(Average marginal effects, size(medium))  ///
    groups (?.act  = "{bf:Service}"                                ///
            ?.qual = "{bf:Quality}"                                ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
			graph save fig2b.gph, replace 			
graph combine fig2a.gph fig2b.gph, xsize(5) ysize(2)
graph save fig2_base.gph, replace			
			

* Figure 3. Conditional Treatment Effects 
xtreg sat i.act i.qual i.period if com==1    , re rob  
margins act qual, post  mcompare(sidak)
estimates store fac
xtreg sat i.act i.qual i.period if com==2   , re rob  
margins act qual, post  mcompare(sidak)
estimates store sst
xtreg sat i.act i.qual i.period if com==3   , re rob  
margins act qual, post  mcompare(sidak)
estimates store app
coefplot (fac, label(Face to Face)) (sst, label(SST))  (app, label(APP)), drop(_cons) baselevels xtitle(Predicted value) legend(cols(3)) ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig3a.gph, replace 
xtreg sat i.act i.qual i.period if com==1    , re rob  
margins, dydx(act qual) post mcompare(sidak)
estimates store fac
xtreg sat i.act i.qual i.period if com==2   , re rob  
margins, dydx(act qual) post mcompare(sidak)
estimates store sst
xtreg sat i.act i.qual i.period if com==3   , re rob  
margins, dydx(act qual) post mcompare(sidak)
estimates store app
coefplot (fac, label(Face to Face)) (sst, label(SST)) (app, label(APP)),  xline(0) xtitle(Average marginal effects)  legend(cols(3)) ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig3b.gph, replace 
graph combine fig3a.gph fig3b.gph, xsize(5) ysize(2)
graph save fig3.gph, replace


* Figure 4. Heterogeneous Treatment Effects (Expectations)
xtreg sat i.act i.qual i.com                    i.period  if exp_nq3==1  , re rob 
margins act qual com, post mcompare(sidak) 
estimates store lo
xtreg sat i.act i.qual i.com                    i.period  if exp_nq3==2  , re rob 
margins act qual com, post mcompare(sidak)
estimates store med
xtreg sat i.act i.qual i.com                    i.period  if exp_nq3==3  , re rob 
margins act qual com, post mcompare(sidak)
estimates store hi
coefplot (lo, label(Low)) (med, label(Medium)) (hi, label(High)), drop(_cons) baselevels xtitle(Predicted value) legend(cols(3)) ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1a.gph, replace 
xtreg sat i.act i.qual i.com                    i.period  if exp_nq3==1  , re rob 
margins , dydx(act qual com) post mcompare(sidak) 
estimates store lo
xtreg sat i.act i.qual i.com                    i.period  if exp_nq3==2  , re rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store med
xtreg sat i.act i.qual i.com                    i.period  if exp_nq3==3  , re rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store hi
coefplot (lo, label(Low)) (med, label(Medium)) (hi, label(High)),  xline(0) xtitle(Average marginal effects)  legend(cols(3)) ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1b.gph, replace 
graph combine fig1a.gph fig1b.gph, title({bf:Expectation}, size(medium)) xsize(10) ysize(4)
graph save fig4_part1.gph, replace


* Figure 4. Heterogeneous Treatment Effects (Gender)
xtreg sat i.act i.qual i.com                    i.period  if fem==1  , re rob 
margins act qual com, post mcompare(sidak) 
estimates store fem
xtreg sat i.act i.qual i.com                    i.period  if fem==0  , re rob 
margins act qual com, post mcompare(sidak)
estimates store male
coefplot (fem, label(Female)) (male, label(Male)), drop(_cons) baselevels xtitle(Predicted value) legend(cols(3))  ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1a.gph, replace 
xtreg sat i.act i.qual i.com                    i.period  if fem==1  , re rob 
margins , dydx(act qual com) post mcompare(sidak) 
estimates store fem
xtreg sat i.act i.qual i.com                    i.period  if fem==0  , re rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store male
coefplot (fem, label(Female)) (male, label(Male)),  xline(0) xtitle(Average marginal effects)  legend(cols(3))  ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1b.gph, replace 
graph combine fig1a.gph fig1b.gph, title({bf:Gender}, size(medium)) xsize(10) ysize(4)
graph save fig4_part2.gph, replace


* Figure 4. Heterogeneous Treatment Effects (Age)
xtreg sat i.act i.qual i.com                    i.period  if age3==1  , re rob 
margins act qual com, post mcompare(sidak) 
estimates store lo
xtreg sat i.act i.qual i.com                    i.period  if age3==2  , re rob 
margins act qual com, post mcompare(sidak)
estimates store med
xtreg sat i.act i.qual i.com                    i.period  if age3==3  , re rob 
margins act qual com, post mcompare(sidak)
estimates store hi
coefplot (lo, label(Age 18-35)) (med, label(Age 36-55)) (hi, label(Age 56+)), drop(_cons) baselevels xtitle(Predicted value) legend(cols(3))  ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1a.gph, replace 
xtreg sat i.act i.qual i.com                    i.period  if age3==1  , re rob 
margins , dydx(act qual com) post mcompare(sidak) 
estimates store lo
xtreg sat i.act i.qual i.com                    i.period  if age3==2  , re rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store med
xtreg sat i.act i.qual i.com                    i.period  if age3==3  , re rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store hi
coefplot (lo, label(Age 18-35)) (med, label(Age 36-55)) (hi, label(Age 56+)),  xline(0) xtitle(Average marginal effects)  legend(cols(3))  ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1b.gph, replace 
graph combine fig1a.gph fig1b.gph, title({bf:Age}, size(medium)) xsize(10) ysize(4)
graph save fig4_part3.gph, replace
			
		
* Online Appendix Figure 1. Satisfaction with procedure vs. outcome
xtreg vpr i.act i.qual i.com                    i.period   , re rob 
margins act qual com, post mcompare(sidak) 
estimates store vpr
xtreg vre i.act i.qual i.com                    i.period   , re rob 
margins act qual com, post mcompare(sidak)
estimates store vre
coefplot (vpr, label(Procedure)) (vre, label(Outcome)), drop(_cons) baselevels xtitle(Predicted value) legend(cols(3))  ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1a.gph, replace 
xtreg vpr i.act i.qual i.com                    i.period   , re rob 
margins , dydx(act qual com) post mcompare(sidak) 
estimates store vpr
xtreg vre i.act i.qual i.com                    i.period   , re rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store vre
coefplot (vpr, label(Procedure)) (vre, label(Outcome)),  xline(0) xtitle(Average marginal effects)  legend(cols(3))  ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1b.gph, replace 
graph combine fig1a.gph fig1b.gph, title({bf:Satisfaction with...}, size(medium)) xsize(10) ysize(4)
graph save fig1_appendix.gph, replace

			
* Online Appendix Figure 2. Effects Heterogeneity by Period
reg sat i.act i.qual i.com                    if period==1  ,  rob 
margins act qual com, post mcompare(sidak) 
estimates store lo
reg sat i.act i.qual i.com                    if period==2  ,  rob 
margins act qual com, post mcompare(sidak)
estimates store med
reg sat i.act i.qual i.com                    if period==3  ,  rob 
margins act qual com, post mcompare(sidak)
estimates store hi
coefplot (lo, label(Period 1)) (med, label(Period 2)) (hi, label(Period 3)), drop(_cons) baselevels xtitle(Predicted value) legend(cols(3)) ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium)) 
graph save fig1a.gph, replace 
reg sat i.act i.qual i.com                    if period==1  ,  rob 
margins , dydx(act qual com) post mcompare(sidak) 
estimates store lo
reg sat i.act i.qual i.com                    if period==2  ,  rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store med
reg sat i.act i.qual i.com                    if period==3  ,  rob 
margins , dydx(act qual com) post mcompare(sidak)
estimates store hi
coefplot (lo, label(Period 1)) (med, label(Period 2)) (hi, label(Period 3)),  xline(0) xtitle(Average marginal effects)  legend(cols(3)) ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
graph save fig1b.gph, replace 
graph combine fig1a.gph fig1b.gph, xsize(5) ysize(2)
graph save fig2_appendix.gph, replace			
		
		
* Online Appendix Figure 3. Baseline Treatment Effects (Alternative Model Specification)
reg sat i.act i.qual i.com                   , cluster(id) 
margins act qual com , post mcompare(bonferroni)
coefplot, xtitle(Predicted value,size(medium))     ///
    groups (?.act  = "{bf:Service}"                  ///
            ?.qual = "{bf:Quality}"                  ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
			graph save fig1a.gph, replace		
reg sat i.act i.qual i.com                    , cluster(id) 
margins, dydx(act qual com) post mcompare(bonferroni)
coefplot, xline(0) xtitle(Average marginal effects, size(medium))  ///
    groups (?.act  = "{bf:Service}"                                ///
            ?.qual = "{bf:Quality}"                                ///
            ?.com  = "{bf:Interface}") ylabel(,labsize(medium)) xlabel(,labsize(medium))
			graph save fig1b.gph, replace 			
graph combine fig1a.gph fig1b.gph, xsize(5) ysize(2)
graph save fig3_appendix.gph, replace	
		
		
* Online Appendix Table 5. Regression results (without accounting for multiple comparisons)
xtreg sat i.act i.qual i.com   i.period                 , re rob 
est store m1
xtreg sat i.act i.qual         i.period   if com==1     , re rob  
est store m2a
xtreg sat i.act i.qual         i.period   if com==2     , re rob  
est store m2b
xtreg sat i.act i.qual         i.period   if com==3     , re rob
est store m2c
xtreg sat i.act i.qual i.com   i.period  if exp_nq3==1  , re rob 
est store m3a
xtreg sat i.act i.qual i.com   i.period  if exp_nq3==2  , re rob 
est store m3b
xtreg sat i.act i.qual i.com   i.period  if exp_nq3==3  , re rob 
est store m3c
xtreg sat i.act i.qual i.com   i.period  if fem==1      , re rob 
est store m4a
xtreg sat i.act i.qual i.com   i.period  if fem==0      , re rob 
est store m4b
xtreg sat i.act i.qual i.com   i.period  if age3==1     , re rob 
est store m5a
xtreg sat i.act i.qual i.com   i.period  if age3==2     , re rob 
est store m5b
xtreg sat i.act i.qual i.com   i.period  if age3==3     , re rob 
est store m5c 
esttab m1 m2a m2b m2c m3a m3b m3c m4a m4b m5a m5b m5c using tab5_online.csv, ///
       se b(a2) brackets star(* 0.10 ** 0.05 *** 0.01) ///
	   stats(N r2_w) label  nogaps replace


**********************
*** Hausman Test   ***
**********************
tsset id period
xtreg sat i.act i.com i.qual exp age i.fem  i.period ,fe  
est store fe
xtreg sat i.act i.com i.qual exp age i.fem  i.period ,re  
est store re
hausman fe re


**********************
*** Balancing Test ***
**********************

tsset id period
recode act  1=1 2=2 3=3
recode com  1=3 2=2 3=1
recode qual 1=1 2=2 3=3
gen vign=.
replace	vign=	1	if act==	1	& com==	1	& qual==	1
replace	vign=	2	if act==	1	& com==	1	& qual==	2
replace	vign=	3	if act==	1	& com==	1	& qual==	3
replace	vign=	4	if act==	1	& com==	2	& qual==	1
replace	vign=	5	if act==	1	& com==	2	& qual==	2
replace	vign=	6	if act==	1	& com==	2	& qual==	3
replace	vign=	7	if act==	1	& com==	3	& qual==	1
replace	vign=	8	if act==	1	& com==	3	& qual==	2
replace	vign=	9	if act==	1	& com==	3	& qual==	3
replace	vign=	10	if act==	2	& com==	1	& qual==	1
replace	vign=	11	if act==	2	& com==	1	& qual==	2
replace	vign=	12	if act==	2	& com==	1	& qual==	3
replace	vign=	13	if act==	2	& com==	2	& qual==	1
replace	vign=	14	if act==	2	& com==	2	& qual==	2
replace	vign=	15	if act==	2	& com==	2	& qual==	3
replace	vign=	16	if act==	2	& com==	3	& qual==	1
replace	vign=	17	if act==	2	& com==	3	& qual==	2
replace	vign=	18	if act==	2	& com==	3	& qual==	3
replace	vign=	19	if act==	3	& com==	1	& qual==	1
replace	vign=	20	if act==	3	& com==	1	& qual==	2
replace	vign=	21	if act==	3	& com==	1	& qual==	3
replace	vign=	22	if act==	3	& com==	2	& qual==	1
replace	vign=	23	if act==	3	& com==	2	& qual==	2
replace	vign=	24	if act==	3	& com==	2	& qual==	3
replace	vign=	25	if act==	3	& com==	3	& qual==	1
replace	vign=	26	if act==	3	& com==	3	& qual==	2
replace	vign=	27	if act==	3	& com==	3	& qual==	3

* Descriptive
histogram vign, discrete freq

* Online Appendix Table 3. Test for uniform random distribution of Vignettes
chitest vign, count sep(0)

* Online Appendix Table 4. Balancing-Test
xtreg vign  exp age i.fem  i.period   , re rob
est store m1
  reg vign  exp age i.fem if period==1, rob
est store m2
esttab m1 m2 using tab_balance.csv, p b(a2) r2 brackets star(* 0.10 ** 0.05 *** 0.01) label scalars(r2_o) nogaps replace
